package com.ziulife.dao;

import com.ziulife.utils.JdbcUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ColumnListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.sql.Connection;
import java.util.List;

/**
 * 基础DAO类，提供通用的数据库操作方法
 * 其他具体DAO类（如UserDao）应继承此类，而不是直接实例化BaseDao
 *
 * @author Administrator
 *
 * @param <T> 泛型参数，表示要映射的Java实体类，如User
 */
public class BaseDao<T> {

	QueryRunner queryRunner = new QueryRunner();

	private Class<T> clazz; // 实体类的Class对象

	@SuppressWarnings("unchecked")
	public BaseDao(){
		// 在BaseDao的构造函数中初始化clazz属性，如User.class
		Type superType = this.getClass().getGenericSuperclass(); // 获取当前类的泛型父类
		if(superType instanceof ParameterizedType) {
			ParameterizedType pt = (ParameterizedType) superType;
			Type[] typeArray = pt.getActualTypeArguments(); // 获取泛型参数数组，第一个元素就是需要的类型T
			if(typeArray[0] instanceof Class) {
				clazz = (Class<T>) typeArray[0];
			}
		}
	}

	/**
	 * 查询数据库，获取SQL查询结果的第一条记录，封装为一个对象返回，支持参数化查询
	 * 使用dbutils的BeanHandler
	 *
	 * @param sql SQL查询语句
	 * @param args SQL参数
	 * @return 查询到的实体对象，如果没有结果则返回null
	 */
	public T get(String sql, Object... args) {
		Connection conn = null;
		T entity = null;
		try {
			conn = JdbcUtils.getConnection();
			entity = queryRunner.query(conn, sql, new BeanHandler<T>(clazz), args);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			JdbcUtils.closeConn(conn);
		}
		return entity;
	}

	/**
	 * 获取查询结果的计数（整数）
	 *
	 * @param sql SQL查询语句
	 * @param args SQL参数
	 * @return 查询结果的计数
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public int getCount(String sql, Object... args) {
		Connection conn = null;
		int count = 0;
		try {
			conn = JdbcUtils.getConnection();
			count = ((Long) queryRunner.query(conn,sql, new ScalarHandler(),args)).intValue();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			JdbcUtils.closeConn(conn);
		}
		return count;
	}

	/**
	 * 获取查询结果的计数（BigDecimal类型），适用于大数字
	 *
	 * @param sql SQL查询语句
	 * @param args SQL参数
	 * @return 查询结果的计数，以BigDecimal形式返回
	 */
	public BigDecimal getBigDecimalCount(String sql, Object... args) {
		Connection conn = null;
		BigDecimal count = BigDecimal.ZERO;
		try {
			conn = JdbcUtils.getConnection();
			Object result = queryRunner.query(conn, sql, new ScalarHandler<>(), args);
			if (result != null) {
				if (result instanceof BigDecimal) {
					count = (BigDecimal) result;
				} else if (result instanceof Number) {
					count = BigDecimal.valueOf(((Number) result).doubleValue());
				} else {
					count = new BigDecimal(result.toString());
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			JdbcUtils.closeConn(conn);
		}
		return count;
	}

	/**
	 * 查询单个字段并返回字符串数组
	 *
	 * @param sql SQL查询语句
	 * @param args SQL参数
	 * @return 字符串数组，包含查询结果
	 */
	public String[] getStringArray(String sql, Object... args) {
		Connection conn = null;
		String[] resultArray = null;
		try {
			conn = JdbcUtils.getConnection();
			// ColumnListHandler会自动返回第一列的数据
			List<String> resultList = queryRunner.query(conn, sql, new ColumnListHandler<String>(), args);
			resultArray = resultList.toArray(new String[0]);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			JdbcUtils.closeConn(conn);
		}
		return resultArray;
	}

	/**
	 * 查询数据库，获取SQL查询结果的第一条记录，封装为一个对象返回（使用外部连接）
	 *
	 * @param conn 数据库连接
	 * @param sql SQL查询语句
	 * @param args SQL参数
	 * @return 查询到的实体对象，如果没有结果则返回null
	 */
	public T get(Connection conn, String sql, Object... args) {
		T entity = null;
		try {
			entity = queryRunner.query(conn, sql, new BeanHandler<T>(clazz), args);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return entity;
	}

	/**
	 * 获取多条记录的通用方法
	 *
	 * @param sql SQL查询语句
	 * @param args SQL参数
	 * @return 包含查询结果的列表
	 */
	public List<T> getList(String sql, Object... args){
		Connection conn = null;
		List<T> list = null;
		try {
			conn = JdbcUtils.getConnection();
			list = queryRunner.query(conn, sql, new BeanListHandler<T>(clazz), args);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			JdbcUtils.closeConn(conn);
		}
		return list;
	}

	/**
	 * 通用的增删改方法（INSERT, UPDATE, DELETE）
	 *
	 * @param sql SQL语句
	 * @param args SQL参数
	 * @return 受影响的行数
	 */
	public int update(String sql, Object... args) {
		Connection conn = null;
		int rows = 0;
		try {
			conn = JdbcUtils.getConnection();
			rows = queryRunner.update(conn, sql, args);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			JdbcUtils.closeConn(conn);
		}
		return rows;
	}

	/**
	 * 通用的查询单个值的方法，如COUNT(id)等聚合函数
	 *
	 * @param sql SQL查询语句
	 * @param args SQL参数
	 * @return 查询结果的单个值
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public Object getValue(String sql, Object... args) {
		Connection conn = null;
		Object obj = null;
		try {
			conn = JdbcUtils.getConnection();
			obj = queryRunner.query(conn, sql, new ScalarHandler(), args);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			JdbcUtils.closeConn(conn);
		}
		return obj;
	}
}